איך לפרוץ קראק מי?

מטרת הטקסט היא להסביר איך ניגשים לתוכנית וללמד עוד דברים בסיסיים בדרך אוקיי אז היום נפצח קראקמי, למצוא אותו פה:
http://66.98.132.48/krobar/beginner/crackme1.zip

נתחיל את העבודה במציאת הסיסמא,לאחר מכן ניגש ליצירת הקראק עצמו,לצורך כך נשתמש ב אולידיבאגר
קודם כדאי סתם להריץ אותו לעצמנו, לבדוק אותו, אולי יש גם השוואות של אורך הסטרינג ומזה גם אנו
צריכים להיזהר עכשיו כשלא שמנו לב לשום דבר מיוחד חוץ מההודעה של הסיסמה הלא נכונה וגם אם לא מוכנס
כלום אז הוא שוב מבקש שיכניסו שזה אומר שיש השוואה ובדיקה של האורך בואו ניפתח אותו בפייד, לא ניהיה
עצלנים וניבדוק אם יש איזו הגנה, ולא אין שום דבר מיוחד –
Microsoft Visual C++ 6.0
מצויין בישבלנו, אוקיי אז עכשיו ניפתח אותו באולי, ונמצא את המקום שאנחנו מחפשים(מחפשים את המקום בו
יש את ההשוואה של מה שהכנסנו ומה שזה באמת) נימצא את המקום ב2 דרכים שונות, מצויין בישביל תרגול.
אז קודם כל תעשו בסיפייו(החלון הראשי של אולי) כפתור שלישי ו-
Search for-> all referenced text string
זה יראה לנו את כל הסטרינגים שבקראקמי, טוב אז אנו עכישו רואים כמות לא גדולה של סטרינגים
ליתר דיוק 6 סטרינגים, אוקיי אז בין הסטרינגים אנו רואים את הסטרינג וההודעה שמופיעה כשלא רושמים כלום,
את ההודעה של השגיאה ואפילו ההודעה שאומרת לנו שהצלחנו,אגב יש גם שם את הסטרינג של הכותרת של הקראקמי.
אז ניכנס לסטרינג של ההודעה הטובה שמאשרת את זה שהצלחנו:
CORRECT WAY TO GO
אז ניסתכל קצת מסביב ואנו רואים שכמה שורות יותר למעלה יש קריאה לפונקציה שמשווה 2 סטרינגים, קוראים לה:
Lstrcmp
טוב אז הגענו לאיפה שרצינו. עכשיו כמו שאמרתי יש עוד דרך להגיע להשוואה
דרך 2
אוקיי בדרך זו פשו נגיע למיקום שלנו על ידיי איתור האפי(הפונקציה) של ההשוואה
זאת עושים על ידיי חלון ה
EXECUTABLE MODULS
אם אין לכם את החלון הזו אתם יוכולים להכנס עליו ע"' לחיצה על
E
אינ לא מדבר על לחיצה על המקלדת אלה על התפריט בצבע התכלת, אוקיי עכשיו יופיע לכם החלון
אוקיי עכשיו בשורה הראשונה באותו תפריט יש כתובת ארוכה של איפה נימצא הקראקמי הזה במחשב שלכם. פה אתם
צריכים לסמן אותו וללחוץ CTRL+N

(NAMES)
עכשיו הופיע לכם חלון עם כל הפונקציות, צריך להיות לכם ידע בסיסי בישביל לדעת איזה פונקציה אתם מחפשים,
לדוגמה אחת הפונקציות כמו שאמרתי שעושות השוואה בין 2 סטרינגים זו
LSTRCMPA
(מי שלא הבין הכוונה סטרינג קומפר)
ולדוגמה הפונקציה
LSTRLENA
היא בודקת את האורך של הסטרינג(פונקציה זו גם משומשת בתכנית)
אוקיי עכשיו אתם שמים ברייקפוינט על כל הופעה של הפונקציה שמשווה 2 סטרינגים
זאת עושים על ידיי סימון הפונקציהף כםתור שלישי ו
SET BREAKPOINT ON EVRY REFERENCE
שזה גם בעצם יעשה חצי מהעבודה
אוקיי אז המטרה של ברייקפוינט בעצם היא שהתוכנית והדיבאגגר יעצרו במקום מסויים אשר אותו אנו בוחרים,
זה עוזר לנו בלגלות איזה מידע עובר באותו מקום, וכאן למשל שמנו ברייקפוינט כדיי למצוא איפה התוכנית
משתמשת בפונקציה של השוואה, אז עכשיו אנו מריצים את התוכנית דרך הדבאגר על ידיי לחיצה על הכפתור הפליי
שליד האפשרויות באולי אז תכניסו איזו סיסמה כמו 123456, אז התוכנית רצה ועוצרת בפונקציה שלנו והנה הגענו למקום.
עכשיו שניה נחזור על מה עושים הלאה אם בחרנו בדרך הראשונה(מציאה ע"י סטרינג) אז פשוט שמים ברייקפוינט
ידנית ע"י לחיצה על המקש F2

שמים את הברייקפוינק בקריאה לפונקציה ומריצים את התכנית. עכשיו אחריי שהכנסתם 123456 ועשיתם צ'ק זה עוצר לכם,
עכשיו אם אתם רואים בחלון של הרג'סטרס ב CPU או בחלון בצד ימין שיותר למטה ב CPU יש

0012F8A8 0012F8C4 |String1 = "123456"
0012F8AC 0012F8B4 \String2 = ""

אז רואים כאן שהסטרינג שהכנסנו זה 123456 מושווה לסטריג2 וזאת אומרת שהסטרינג 2 נכון:
עכשיו אתם יוכולים להריץ את התוכנית בנפרד ולהכניס את הסיסמה הזו וזה יעבוד
עכשיו בואו ננתח את כל האסמבלי שמה ונעשה רוורסינג

0040155F |. 50 PUSH EAX ; /String הפונקציה שמתחת מכניסה את מיספר התווים
00401560 |. FF15 04204000 CALL DWORD PTR DS:[<&KERNEL32.lstrlenA>] ; \lstrlenA קריאה לפונקציה לבדיקה של מספר התווים בסיסמה
00401566 |. 8945 F0 MOV DWORD PTR SS:[EBP-10],EAX העברה
00401569 |. 837D F0 01 CMP DWORD PTR SS:[EBP-10],1 השוואה של אורך הסיסמה עם 1
0040156D |. 73 16 JNB SHORT crackme1.00401585 אם האורך של הסיסמה שהכנסנו גדול או שווה ל1 קופצים
0040156F |. 6A 40 PUSH 40
00401571 |. 68 2C304000 PUSH crackme1.0040302C ; ASCII "CrackMe"
00401576 |. 68 34304000 PUSH crackme1.00403034 ; ASCII "Enter Registration Number" בקשה להכנסה של סיסמה בגלל שלא הכנסנו כלום ובשורות הבאות חוזרים
0040157B |. 8B4D E0 MOV ECX,DWORD PTR SS:[EBP-20]
0040157E |. E8 7B050000 CALL
00401583 |. EB 3C JMP SHORT crackme1.004015C1
00401585 |> 8D4D E4 LEA ECX,DWORD PTR SS:[EBP-1C]
00401588 |. 51 PUSH ECX ; /String2 הערך שמושווה בו(הסיסמה האמיתית)
00401589 |. 8D55 F4 LEA EDX,DWORD PTR SS:[EBP-C] ; |
0040158C |. 52 PUSH EDX ; |String1 הערך שצריך להשוות(מה שהכנסנו)
0040158D |. FF15 00204000 CALL DWORD PTR DS:[<&KERNEL32.lstrcmpA>] ; \lstrcmpA קריאה לפונקציה
00401593 |. 85C0 TEST EAX,EAX בודק עם 2 הסיסמאות זהות אם כן זה 0
00401595 |. 75 16 JNZ SHORT crackme1.004015AD אם לא זהות \ לא שווה 0 אז זה יקפוץ

אוקיי בואו ניראה מה קורה הלאה:

00401599 |. 68 50304000 PUSH crackme1.00403050 ; ASCII "CrackMe"
0040159E |. 68 58304000 PUSH crackme1.00403058 ; ASCII "Correct way to go!!" אם לא קפץ אז זה ההודעה הטובה
004015A3 |. 8B4D E0 MOV ECX,DWORD PTR SS:[EBP-20]
004015A6 |. E8 53050000 CALL חוזר לתפריט
004015AB |. EB 14 JMP SHORT crackme1.004015C1
004015AD |> 6A 40 PUSH 40
004015AF |. 68 6C304000 PUSH crackme1.0040306C ; ASCII "CrackMe" לפה הוא קופץ אם הסטרינגים לא שווים
004015B4 |. 68 74304000 PUSH crackme1.00403074 ; ASCII "Incorrect try again!!"
004015B9 |. 8B4D E0 MOV ECX,DWORD PTR SS:[EBP-20]
004015BC |. E8 3D050000 CALL חוזר לתפריט


טוב אז מה שעושים עכשיו זה לערוך את הקראק ולשמור, מה שנעשה זה שנוריד את ההשוואה של אורך הסטרינג
וגם נעשה שכל סיסמה תיהיה נכונה וכל זה כבר שטויות אחריי שאנו יודעים את תוכן התוכנית ועשינו לה רוורסינג
אוקיי אז נתחיל בזה שנעשה שכל סיסמה אפשרית יש הרבה דריכים אני יראה 2 בסיסיות:
JNZ SHORT crackme1.004015AD

אז כמו שאמרנו כאן זה הקפיצה המותנית אם הסטרינגים שווים זה יקפוץ
אז אפשר פשוט לשנות את ה
JNZ ל JZ
או
JNZ
ל-
NOP
הפקודה נופ לא עושה כלום ובעצם זה לא יקפוץ
JZ אז הפקודה הזו תיקפוץ אם הערכים שווים שזה גם טוב בישבילנו כי ככה 99.99999 אחוז שזה יראה את ההודעה הטובה.
אוקיי עכשיו כשסיימנו עם זה יש לנו לעשות את הבדיקה של האורך, גם כאן יש יותר מדרך אחת:

00401569 |. 837D F0 01 CMP DWORD PTR SS:[EBP-10],1
0040156D |. 73 16 JNB SHORT crackme1.00401585

כאן השוואה וקפיצה אז פשוט נשנה את JNB ל JMP ככה שתמיד יקפוץ, במקרה זה אי אפשר לשנות ל JB
אז תיהיה הודעה טובה\יקפוץ רק אם לא הכנסנו כלום
להזכירכם JNB = Jump (if) Not Below

וזה קופץ אם 1 לא יותר גדול מכמות התווים שהכנסנו

מקווה שעזרתי
XiR0x